package com.ruoyi.system.coretools.apple;

import com.ruoyi.common.exception.ServiceException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.PublicKey;

/**
 * APPLE的登录原理
 * 首先，当你在应用内点击苹果登陆按钮时，苹果会生成一系列的参数给你，其中最重要的一个参数是：identityToken。这个参数的值就是一个JWT。这个JWT是通过苹果的私钥加密的。
 * 我们将这个identityToken传给我们的后台服务，后台服务从苹果提供的公钥下载地址下载公钥，然后使用公钥验证这个JWT是否合法。
 * 在合法的前提下，我们看一下iss是否是苹果（显然是），再看aud是不是你自己的包名（别人的应用也可以生成一个token，也可以通过校验，但是包名肯定和你的不同）。都校验通过了，说明这是一个合法JWT。
 * 然后我们就取sub作为苹果的OpenId，记录到我们后台的用户表里即可（如果没有用户则创建，如果有则绑定）。等到再次登录的时候，则用sub查询有没有对应的用户，如果有，则直接让其登录即可。
 */
public class AppleAuthHelper {
    private static final Logger log = LoggerFactory.getLogger(AppleAuthHelper.class);
    private static final String PUBLIC_KEY_URL = "/auth/keys";
    private static final String APPLE_DOMAIN = "https://appleid.apple.com";
    //苹果包名后面做成配置，要与发到苹果appstore的一致，判断中要用
    private static final String aud = "com.test";

    /**
     * 校验苹果登录信息
     *
     * @param appleAuthRequest
     * @return
     */
    public static boolean isValid(AppleAuthRequest appleAuthRequest) {
        try {
            IdentityToken idToken = new IdentityToken(appleAuthRequest.getIdentityToken());
            String userID = appleAuthRequest.getUserID();
            PublicKey publicKey = AppPublicKey.get(APPLE_DOMAIN + PUBLIC_KEY_URL, idToken.getKid());
            if (null == publicKey) {
                return false;
            }
            JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);
            jwtParser.requireIssuer(APPLE_DOMAIN);
            jwtParser.requireAudience(aud);
            jwtParser.requireSubject(userID);
            Jws<Claims> claim = jwtParser.parseClaimsJws(idToken.getToken());
            if (claim != null && claim.getBody().containsKey("auth_time")) {
                return true;
            }
        } catch (Exception e) {
            log.error("校验apple登录信息失败", e);
        }
        return false;
    }


    /**
     * 业务用验证
     *
     * @param identityToken
     * @param userID
     * @return
     */
    public static String isValid(String identityToken, String userID) {
        try {
            IdentityToken idToken = new IdentityToken(identityToken);
            PublicKey publicKey = AppPublicKey.get(APPLE_DOMAIN + PUBLIC_KEY_URL, idToken.getKid());
            if (null == publicKey) {
                throw new ServiceException("公钥与校验失败");
            }
            JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);
            jwtParser.requireIssuer(APPLE_DOMAIN);
            jwtParser.requireAudience(aud);
            jwtParser.requireSubject(userID);
            Jws<Claims> claim = jwtParser.parseClaimsJws(idToken.getToken());
            if (claim != null && claim.getBody().containsKey("auth_time")) {
                //用它当openId,记录到我们后台的用户表里即可（如果没有用户则创建，如果有则绑定）
                //return claim.getBody().getSubject();

                //claim.getBody().containsKey("email");
                return claim.getBody().get("email").toString();


            } else {
                throw new ServiceException("认证失败，缺少认证时间字段.");
            }
        } catch (Exception e) {
            log.error("校验apple登录信息失败", e);
            throw e;
        }

    }

}
